const defaultOpts = {};

const ps = {
  init(env) {
    env.next = null;
    env.names = {};
  },
  Program(node, env, opts) {
    // TODO: Program, Block 和 VariableDeclaration都是类似的循环
    const index = opts.index || 0;
    let item = node.body[index];
    return ps.process(item, env).then(() => {
      if (index === node.body.length - 1) {
        env.next = null; // done
      } else {
        return ps.process(node, env, {
          index: index + 1,
        });
      }
    });
  },
  VariableDeclaration(node, env, opts) {
    const index = opts.index || 0;
    let item = node.declarations[index];
    return ps.process(item, env).then(() => {
      if (index === node.declarations.length - 1) {
        // done
      } else {
        return ps.process(node, env, {
          index: index + 1,
        });
      }
    });
  },
  VariableDeclarator(node, env) {
    const arr = [
      ps.process(node.id, env, { name: true })
    ];
    arr.push(node.init ? ps.process(node.init, env) : Promise.resolve(undefined));
    return Promise.all(arr).then((l) => {
      const [left, right] = l;
      env.names[left] = right;
    });
  },
  Identifier(node, env, opts) {
    if (!opts.name) return Promise.resolve(env.names[node.name]);
    return Promise.resolve(node.name);
  },
  Literal(node, env) {
    return Promise.resolve(eval(node.raw));
  },
  WhileStatement(node, env) {
    return ps.process(node.test, env).then((flag) => {
      if (flag) {
        return ps.process(node.body, env).then(() => {
          return ps.process(node, env)
        });
      } else {
        // done
      }
    });
  },
  IfStatement(node, env) {
    return Promise.resolve(ps.process(node.test, env)).then((flag) => {
      if (flag) return ps.process(node.consequent, env);
      return ps.process(node.alternate, env)
    });
  },
  BinaryExpression(node, env) {
    return Promise.all([
      ps.process(node.left, env),
      ps.process(node.right, env)
    ]).then((arr) => {
      const [left, right] = arr;
      switch (node.operator) {
        case '<=': {
          return left <= right;
        }
        case '<': {
          return left < right;
        }
        case '+': {
          return left + right;
        }
      }
    });
  },
  BlockStatement(node, env, opts) {
    const index = opts.index || 0;
    let item = node.body[index];
    return ps.process(item, env).then(() => {
      if (index === node.body.length - 1) {
        // done
      } else {
        return ps.process(node, env, {
          index: index + 1,
        });
      }
    });
  },
  ExpressionStatement(node, env) {
    return ps.process(node.expression, env);
  },
  AssignmentExpression(node, env) {
    return Promise.all([
      ps.process(node.left, env, { name: true }),
      ps.process(node.right, env)
    ]).then((arr) => {
      const [left, right] = arr;
      switch (node.operator) {
        case '=': {
          env.names[left] = right;
          break;
        }
      }
    });
  },
  process(node, env, opts) {
    const p = ps[node.type];
    if (!p) {
      console.error('未处理的类型', node.type, node);
      return;
    }
    const result = p(node, env, opts || defaultOpts);
    if (result instanceof Promise) {
      return result;
    }
    return Promise.resolve(result);
  },
};

export default ps;
